//any.cpp实现我们自己的通用容器any，any可以存储任意类型的值

#include <iostream>
#include <any>
#include <typeinfo>
#include <cassert>

//any类的实现
//我们使用多态实现any类型的实现，保存父类holder的指针，子类对象placeholder继承父类
//我们将接受到的不同类型的数据使用模版保存在子类中
class Any
{
    private:
        //这是我们的父类holder
        class holder 
        {
            public:
                //设置为纯虚函数确保不会被实例化，也为了实现虚函数的重写
                virtual const std::type_info& type()=0; //返回子类成员类型
                virtual holder *clone()=0; //克隆父类对象函数
                virtual ~holder(){} //父类的析构函数
        };

        //不同类型的子类对象placeholder，继承自父类holder
        template<class T>
        class placeholder:public holder
        {
            public:
                placeholder(const T&val):_val(val){} //这是子类的构造函数

                //获取子类对象保存的数据类型
                virtual const std::type_info& type() {return typeid(T);}
                
                //针对当前的对象本身，克隆一个新的子类对象
                virtual holder *clone() {return new placeholder(_val);}

            public:
                T _val; //_val就是我们接受到的数据类型
        };
    
    private:
        holder *_content; //any保存父类对象的指针，以便实现多态

    public:
        Any():_content(NULL) {} //Any类的构造函数

        template<class T>
        Any(const T &val):_content(new placeholder<T>(val)) {} //使用子类对象构造Any类

        Any(const Any &other)
        :_content(other._content?other._content->clone():NULL) {} //使用其他Any类对象构造Any类

        ~Any() {delete _content;} //Any的析构函数

        Any &swap(Any &other) //交换函数
        {
            std::swap(_content,other._content);
            return *this;
        }

        //重要，返回子类对象保存的数据的指针
        template<class T>
        T *get()
        {
            //获取的数据类型必须和保存的一致
            assert(typeid(T)==_content->type());
            return &(((placeholder<T>*)_content)->_val); //父类指针强制类型转换子类指针
        }

        //对于子类对象的赋值运算符的重载函数
        template<class T>
        Any& operator=(const T&val)
        {
            //为val构造一个临时的通用容器，然后与当前容器自身进行指针交换
            //临时对象释放的时候，原先保存的数据也就被释放
            Any(val).swap(*this);
            return *this;
        }

        //对于Any类对象的赋值运算符的重载函数
        Any& operator=(const Any &other)
        {
            Any(other).swap(*this);
            return *this;
        }
};

//any类测试，有无内存泄漏问题
class Test
{
    public:
        Test() {std::cout<<"Test构造"<<std::endl;}    
        Test(const Test &t) {std::cout<<"Test拷贝构造"<<std::endl;}
        Test& operator=(const Test &t) {std::cout<<"Test运算符重载"<<std::endl;return *this;}
        ~Test() {std::cout<<"Test析构"<<std::endl;}
};

//测试实现的通用容器any的功能
int main()
{
    //C++17
    //any通用的容器，可以存储任意类型的值
    std::any a;
    a=10;
    int *pi=std::any_cast<int>(&a); //此时any的类型为int
    std::cout<<*pi<<std::endl;
    
    a=std::string("你好");
    std::string *ps=std::any_cast<std::string>(&a); //此时any的类型为string
    std::cout<<*ps<<std::endl;
    
    Test t; //构造一个Test类t
    Test tt;
    tt=t; //运算符重载
    a=t; //a进行拷贝构造
    //a=Test();

    //自己实现的any类测试
    Any ma;
    ma = 10;
    int *pma = ma.get<int>();
    std::cout << *pma << std::endl;
    ma = std::string("nihao");
    std::string *pms = ma.get<std::string>();
    std::cout << *pms << std::endl;

    return 0;
}